package com.jenkins.test.function;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;

/**
 * @version V1.0.0
 * @ClassName: {@link CalcAwardHandler}
 * @Description: AwardService
 * @author: Lanzhou
 * @date: 2022/1/20 11:42
 * @Copyright:2020 All rights reserved.
 */
@Slf4j
@Service
public class CalcAwardHandler {

    @Resource
    private AwardService awardService;

    private Map<String, Function<String, Object>> funcStrategy = new HashMap<>();

    @PostConstruct
    public void initHandlerChain() {
        // 反射获取方法上面的注解然后添加进去
        Class<AwardService> aClass = AwardService.class;
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            AwardType awardType = method.getAnnotation(AwardType.class);
            Optional.ofNullable(awardType).ifPresent(at -> {
                String type = at.value();
                funcStrategy.put(type, param -> {
                    try {
                        return method.invoke(awardService, param);
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        log.warn("初始化方法出错, 请检查当前类型: {} 是否存在对应的方法", type);
                        throw new RuntimeException("初始化方法执行出错, 请稍后重试");
                    }
                });
            });
        }
    }

    /**
     * 获取当前的执行计划结果
     *
     * @param type  类型
     * @param param 参数
     * @return 结果
     */
    public Object getResult(String type, String param) {
        //Controller根据 类型和参数去执行我们需要的结果
        Function<String, Object> result = funcStrategy.get(type);
        if (result != null) {
            //传入resourceId 执行这段表达式获得String型的grantType
            return result.apply(param);
        }
        return "该奖金计算方式没法识别";
    }

    public Map<String, Function<String, Object>> getFuncStrategy() {
        return funcStrategy;
    }

    public void setFuncStrategy(Map<String, Function<String, Object>> funcStrategy) {
        this.funcStrategy = funcStrategy;
    }
}
